/* buffer.c for MudOS 0.9.x by John Garnett, 1993/11/07 */

#include "std.h"

#ifndef NO_BUFFER_TYPE
#include "crctab.h"
#include "lpc_incl.h"
#include "stralloc.h"

buffer_t null_buf =
{
    1,				/* Ref count, which will ensure that it will
				 * never be deallocated */
    0				/* size */
};

INLINE buffer_t *
       null_buffer()
{
    null_buf.ref++;
    return &null_buf;
}				/* null_buffer() */

INLINE void
free_buffer P1(buffer_t *, b)
{
    b->ref--;
    /* don't try to free the null_buffer (ref count might overflow) */
    if ((b->ref > 0) || (b == &null_buf)) {
	return;
    }
    FREE((char *) b);
}				/* free_buffer() */

buffer_t *
allocate_buffer P1(int, size)
{
    buffer_t *buf;

#ifndef NO_BUFFER_TYPE
    if ((size < 0) || (size > max_buffer_size)) {
	error("Illegal buffer size.\n");
    }
    if (size == 0) {
	return null_buffer();
    }
    /* using calloc() so that memory will be zero'd out when allocated */
    buf = (buffer_t *) DCALLOC(sizeof(buffer_t) + size - 1, 1,
				    TAG_BUFFER, "allocate_buffer");
    buf->size = size;
    buf->ref = 1;
    return buf;
#else
    return NULL;
#endif
}

int write_buffer P4(buffer_t *, buf, int, start, char *, str, int, theLength)
{
    int size;

    size = buf->size;
    if (start < 0) {
	start = size + start;
	if (start < 0) {
	    return 0;
	}
    }
    /*
     * can't write past the end of the buffer since we can't reallocate the
     * buffer here (no easy way to propagate back the changes to the caller
     */
    if ((start + theLength) > size) {
	return 0;
    }
    memcpy(buf->item + start, str, theLength);
    return 1;
}				/* write_buffer() */

char *
read_buffer P4(buffer_t *, b, int, start, int, len, int *, rlen)
{
    char *str;
    int size;
    
    if (len < 0)
	return 0;

    size = (int)b->size;
    if (start < 0) {
	start = size + start;
	if (start < 0) {
	    return 0;
	}
    }
    if (len == 0) {
	len = size;
    }
    if (start >= size) {
	return 0;
    }
    if ((start + len) > size) {
	len = (size - start);
    }
    for (str = (char *)b->item + start, size = 0; *str && size < len; str++, size++)
	;
    str = new_string(size, "read_buffer: str");
    memcpy(str, b->item + start, size);
    str[*rlen = size] = '\0';

    return str;
}				/* read_buffer() */
#endif
